#include <jni.h>
#include <string>
#include <android/native_window_jni.h>
#include <unistd.h>
#include <zconf.h>
#include <android/log.h>
#include "NEFFmpeg.h"

extern "C" {
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}

JavaVM *javaVM = 0;
NEFFmpeg *ffmpeg = 0;
ANativeWindow *window = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//静态初始化mutex

jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    javaVM = vm;
    return JNI_VERSION_1_4;
}

/**
 * 渲染画面
 * @param src_data
 * @param src_lineSize
 * @param width
 * @param height
 */
//1，data;2，linesize；3，width; 4， height
void renderFrame(uint8_t *src_data, int src_lineSize, int width, int height) {
    pthread_mutex_lock(&mutex);

    if (!window) {
        pthread_mutex_unlock(&mutex);
        return;
    }
    ANativeWindow_setBuffersGeometry(window, width,
                                     height,
                                     WINDOW_FORMAT_RGBA_8888);
    ANativeWindow_Buffer window_buffer;
    if (ANativeWindow_lock(window, &window_buffer, 0)) {
        ANativeWindow_release(window);
        window = 0;
        pthread_mutex_unlock(&mutex);
        return;
    }
    //把buffer中的数据进行赋值（修改）
    uint8_t *dst_data = static_cast<uint8_t *>(window_buffer.bits);
    int dst_lineSize = window_buffer.stride * 4;//ARGB
    //逐行拷贝
    for (int i = 0; i < window_buffer.height; ++i) {
        memcpy(dst_data + i * dst_lineSize, src_data + i * src_lineSize, dst_lineSize);
    }
    ANativeWindow_unlockAndPost(window);

    pthread_mutex_unlock(&mutex);
}

/**
 * 准备媒体资源
 */
extern "C"
JNIEXPORT void JNICALL
Java_com_junt_avplayer_NEPlayer_prepareNative(JNIEnv *env, jobject thiz, jstring data_source_) {
    const char *dataSource = env->GetStringUTFChars(data_source_, 0);
    JavaCallHelper *javaCallHelper = new JavaCallHelper(env, thiz, javaVM);

    ffmpeg = new NEFFmpeg(javaCallHelper, const_cast<char *>(dataSource));
    ffmpeg->setRenderCallback(renderFrame);
    ffmpeg->prepare();
    env->ReleaseStringUTFChars(data_source_, dataSource);
}

/**
 * 开始播放
 */
extern "C"
JNIEXPORT void JNICALL
Java_com_junt_avplayer_NEPlayer_startNative(JNIEnv *env, jobject thiz) {
    if (ffmpeg) {
        ffmpeg->start();
    }
}

/**
 * 设置surface
 */
extern "C"
JNIEXPORT void JNICALL
Java_com_junt_avplayer_NEPlayer_setSurfaceNative(JNIEnv *env, jobject thiz, jobject surface) {
    // TODO: implement setSurfaceNative()
    pthread_mutex_lock(&mutex);
    if (window) {
        ANativeWindow_release(window);
        window = 0;
    }
    window = ANativeWindow_fromSurface(env, surface);
    pthread_mutex_unlock(&mutex);
}